package com.espirit.eap.util.tagAdaptor;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import com.espirit.eap.pagelayout.Element;
import com.espirit.eap.pagelayout.GridSection;
import com.espirit.eap.pagelayout.Layout;
import com.espirit.eap.pagelayout.Model;
import com.espirit.eap.pagelayout.ModelService;
import com.espirit.eap.pagelayout.PageCache;
import com.espirit.eap.pagelayout.TagInfo;
import com.espirit.eap.util.Functions;
import com.googlecode.cswish.struts.Invoker;
import com.googlecode.cswish.struts.spring.BeanIntrospector;
import com.googlecode.cswish.struts.spring.ModelPropertyInfo;

@Service
public class TagGridSectionAdaptor implements TagElementAdaptor<GridSection> {

	@Resource
	private Functions functions;
	
	@Resource
	private BeanIntrospector beanIntrospector;
	
	@Resource
	private TagAdaptorUtil tagAdaptorUtil;
	
	@Resource
	private ModelService modelService;
	
	@Override
	public TagInfo getTagProperties(Layout root, GridSection element, Map<String, Object> context) {
		GridSection gridSection = element;
		TagInfo tagInfo = new TagInfo(true);
		tagInfo.setContainer(true);
		Map<String, Object> properties = tagInfo.getTagProperties();
		String name = tagAdaptorUtil.getName(element);
		properties.put("name", name);
		
		boolean isRead = true;
		if (gridSection.getReadOnly() != null) {
			isRead = gridSection.getReadOnly();
		}
		String tagName = element.getTagName();
		if (tagName == null) {
			tagName = isRead ? "pageinfo" : "datagrid";
		}
		
		String namePrefix = gridSection.getNamePrefix();
		if (namePrefix == null) {
			namePrefix = "";
		}
		properties.put("namePrefix", namePrefix);		// this is the default namePrefix
		
		Invoker invoker = (Invoker) context.get(INVOKER);
		String simpleModelName = beanIntrospector.getSimpleName(invoker.actionName);
		String modelName = beanIntrospector.getModelName(simpleModelName);
		
		if (isRead) {
			String path = gridSection.getExProperty("path");
			if (path == null) {
				// default path
				String searchMethod;
				if (invoker.isInputMethod()) {
					searchMethod = invoker.getSubmitMethod();
				} else {
					searchMethod = invoker.methodName;
				}
				String searchLink = functions.linkModelNoBase(modelName, searchMethod);
				path = functions.linkNoBase(searchLink, false);
				properties.put("path", path);
			}
			
			// default rowClickLinks
			
			// dblClick, dblClickPath
			String dblClickPath = gridSection.getExProperty("dblClickPath");
			if (dblClickPath == null) {
				dblClickPath = functions.linkModelNoBase(modelName, "_update") + "?model.id=";
				properties.put("dblClickPath", dblClickPath);
			}
		}
		
		String model = gridSection.getExProperty("model");
		if (model == null) {
			String genericListType = null;
			int index = namePrefix.indexOf('.');			// skip the first 'model' and 'execute'
			if (index > 0) {
				genericListType = beanIntrospector.getPropertyType(modelName, namePrefix.substring(index + 1));
			}
			if (genericListType == null) {
				genericListType = modelName;
			}
			properties.put("model", genericListType);
		}
		
		// extra properties
		Map<String, String> exProperties = gridSection.getExProperties();
		if (exProperties != null) {
			properties.putAll(exProperties);
		}
		
		tagInfo.setTagName(tagName);
		return tagInfo;
	}
	
	@Override
	public String getTagName(GridSection element) {
		GridSection gridSection = element;
		boolean isRead = true;
		if (gridSection.getReadOnly() != null) {
			isRead = gridSection.getReadOnly();
		}
		return isRead ? "pageinfo" : "datagrid";
	}

	@Override
	public GridSection updateToElement(Map<String, String> tagProperties, GridSection existed, Map<String, Object> context, PageCache pageCache) {
		GridSection gridSection = existed;
		
		Map<String, Object> defaultTagProperties = (Map<String, Object>) context.get(DEFAULT_TAG_PROP);
		
		// for the legacy code, remove rowClickLinks etc, force store the properties
		Map<String, Object> defaultTagPropertiesCopy = new HashMap<String, Object>(defaultTagProperties);
		defaultTagPropertiesCopy.remove("rowClickLinks");
		defaultTagPropertiesCopy.remove("dblClickPath");
		
		tagAdaptorUtil.updateElement(tagProperties, defaultTagPropertiesCopy, gridSection);

		return gridSection;
	}

	@Override
	public GridSection addElement(Element parent, String tagName, Map<String, Object> properties, PageCache pageCache) {
		Integer index = pageCache.increaseMaxId();
		GridSection gs = new GridSection();
		gs.setId(-index);
		String namePrefix = tagAdaptorUtil.getNamePrefix(parent);
		String name = (String) properties.get("name");
		if (name == null) {
			// name
			name = tagAdaptorUtil.createName(pageCache.getLayout(), tagName);
		}
		if ("pageinfo".equals(tagName)) {
			gs.setReadOnly(true);
			gs.setName(name);
			
			if (namePrefix != null) {
				gs.setNamePrefix(name);
			} else {
				gs.setNamePrefix("execute");
			}
		} else {
			gs.setReadOnly(false);
			gs.setName(name);
			
			if (namePrefix != null) {
				gs.setNamePrefix(name);
			} else {
				gs.setNamePrefix("model." + name);
			}
		}
		gs.setTagName(tagName);
		gs.setDisableAutoSearch(true);
		gs.setColsPerRow(999);
		
		Layout root = pageCache.getLayout();
		// at present, pageinfo and datagrid don't support the nested container
		if (parent != null && GridSection.class.isAssignableFrom(parent.getClass())) {
			parent = parent.getParent();
		}
		tagAdaptorUtil.addToParent(gs, root, parent, properties);

		if (!gs.getReadOnly()) {
			Model model = pageCache.getModel();
			String modelName = beanIntrospector.getModelName(model.getName());
			ModelPropertyInfo mpi = beanIntrospector.getModelPropertyInfo(modelName, name);
			String newModelName;
			if (mpi != null) {
				newModelName = mpi.propertyInfo.getGenericType();
			} else {
				newModelName = modelName.substring(0, modelName.lastIndexOf('.') + 1)
					+ StringUtils.capitalize(gs.getName());
			}
			gs.addExProperty("model", newModelName);
		}
		return gs;
	}

	@Override
	public void deleteElement(Element parent, GridSection existed, PageCache pageCache) {
	}
};